package com.swust.dumpling.commons.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;

import com.swust.dumpling.commons.SystemMessage;

/**
 * @author swust-cs-Dong6 B425
 * 这个类可以从本机塞选出自己想要找的包含给定后缀名的文件.
 * 可以执行文件拷贝操作,但是得指出目标文件夹,并且可读.
 * 
 * This class can choose the file that contains the given extension 
 * you want to find from the local plug.
 * You can perform file copy operations, 
 * but point out that the destination folder, 
 * and the folder must be readable.
 * */
public class CopyFile {
	
	public static String S = SystemMessage.PATH_SYMBOL;
	/**
	 * 被拷贝的文件后缀名
	 * 
	 * copied file file extensions
	 * */
	public static String TYPE = null;
	public static List<String> TYPE_LIST = null;
	/**
	 * 缓存大小
	 * */
	public static int BUFFERED_SIZE = 1024;
	
	/**
	 * init
	 * */
	File RES_DIR = null;
	File TAR_DIR = null;
	File TMP_DIR = null;
	
	File RES_FILE = null;
	File TAR_FILE = null;
	
	InputStream is = null;
	OutputStream os = null;
	
	public CopyFile() {}
	
	public static CopyFile getCopyFile() {
		return new CopyFile();
	}
	/**
	 * list 存放容纳中的文件路径
	 * dir 为被扫描根目录
	 * check true 表示 后缀扫描
	 * check false 表示文件名包含扫描
	 * */
	private void getAllPath(List<String> list , String dir , boolean check) {
		
		RES_DIR = new File(dir);
		
		if ( ! RES_DIR.exists() )
			throw new NullPointerException("input dir must be exist in local ! dir : " + dir);
		
		String[] all = RES_DIR.list();
		
		for (String i : all) {
			
			TMP_DIR = new File(dir + S+ i);
			
			if (TMP_DIR.isDirectory())
				getAllPath(list , dir + S + i , check);
			
			else if( check && i.endsWith(TYPE) )
				list.add(TMP_DIR.getAbsolutePath());
			
			else if( !check && i.indexOf(TYPE) != -1 )
				list.add(TMP_DIR.getAbsolutePath());
		}
	}
	
	
	/**
	 * 
	 * @param rootdir 被扫描的根文件夹
	 * @param cont 被扫描的文件关键字
	 * @param check 关键字后缀,包含
	 * 
	 * */
	private List<String> find(String rootdir , String cont , boolean check) {
		if (rootdir == null || cont == null)
			throw new NullPointerException("DIR or EXTENSION must not be null !");
		List<String> list = 
				new LinkedList<String>();
		TYPE = cont;
		getAllPath(list , rootdir , check);
		return list;
	}
	
	/**
	 * 通过指定的dir路径,指定的文件   后缀名  找到当前路径下所有包含该后缀名的文件
	 * @notice
	 * Dir path specified by the file extension specified files
	 * in the current directory to find all containing the extension
	 * 
	 * @param rootdir root dir name
	 * @param extension file extension
	 * 
	 * @return a list of find file . 
	 * if null , a list with 0 size
	 * */
	public List<String> findPath(String rootdir , String extension) {
		return find(rootdir ,  extension , true);
	}
	
	/**
	 * 通过指定的dir路径,指定的文件   后缀名链表  找到当前路径下所有包含该后缀名的文件
	 * @notice
	 * Dir path specified by the file extension specified files
	 * in the current directory to find all containing the extension
	 * 
	 * @param rootdir root dir name
	 * @param List<extension> file extension
	 * 
	 * @return a list of find file
	 * if null , a list with 0 size
	 * */
	public List<String> findPath(String rootdir , List<String> extension) {
		if (extension == null) 
			throw new NullPointerException("list can`t be null!");
		List<String> list = new LinkedList<String>();
		for (int i = 0 ; i < extension.size() ; i ++) {
			list.addAll(find(rootdir ,  extension.get(i) , true));
		}
		return list;
	}
	
	/**
	 * 通过指定的dir路径, 在所有文件中找到 包含 指定文件名的文件
	 * @notice
	 * 
	 * Path specified by dir,
	 * locate the file containing the specified file name in all documents
	 * 
	 * @param rootdir root dir name
	 * @param cont file
	 * @param tt a random number
	 * 
	 * @return a list of find file , 
	 * if null , a list with 0 size
	 * */
	public List<String> findPath(String rootdir , String cont , int tt) {
		return find(rootdir ,  cont , false);
	}
	
	/**
	 * 通过指定的dir路径, 在所有文件中找到 包含 指定文件名的文件
	 * @notice
	 * 
	 * Path specified by dir,
	 * locate the file containing the specified file name in all documents
	 * 
	 * @param rootdir root dir name
	 * @param cont file 
	 * 
	 * @return a list of find file
	 * if null , a list with 0 size
	 * */
	public List<String> findPath(String rootdir , List<String> extension , int tt) {
		if (extension == null) 
			throw new NullPointerException("list can`t be null!");
		List<String> list = new LinkedList<String>();
		for (int i = 0 ; i < extension.size() ; i ++) {
			list.addAll(find(rootdir ,  extension.get(i) , false));
		}
		return list;
	}
	
	/**
	 * 文件拷贝的方法.在给定的文件夹里面找到包含传参作为后缀或者包含的文件名,并将其拷贝到目标文件夹
	 * 遇到文件夹依次拷贝
	 * 
	 * @param resDir resource root folder
	 * @param tarDir target root folder
	 * @param extention the name extended
	 * @param isInclude TRUE:this is the extension of file : FALSE the target file name includes extension
	 * @throws Exception 
	 * @notice 
	 * File copy method :
	 * found inside pass parameter contains the file name as a suffix in the given folder , 
	 * then copied to the destination folder . copy the folder by turns
	 * */
	public void copyFile(String resDir , String tarDir , String extension , boolean isInclude) throws Exception{
		
		List<String> list = null ;
		
		if (isInclude) 
			list = this.findPath(resDir, extension);
		else
			list = this.findPath(resDir, extension, 0);
		
		resDir = resDir.lastIndexOf(S) == resDir.length() - 1 ?
				resDir.substring(0 , resDir.length() -1) : resDir;
		
		//找到源文件夹的最末一个文件夹起始序列号
		int root = resDir.lastIndexOf(S)+1 ;
		
		String tarRoot = null;
		
		String tmpDir = null;
		
		for (String one : list) {
			RES_FILE = new File(one);
			
			//截取源文件夹最后一个文件夹名称紧跟目标文件夹后
			one = one.substring(root , one.length());
			tarRoot = tarDir + S + one;
			
			tmpDir = tarRoot.substring(0, tarRoot.lastIndexOf(S));
			
			TMP_DIR = new File(tmpDir);
			
			if (!TMP_DIR.exists())
				TMP_DIR.mkdirs();
			
			TAR_FILE = new File(tarRoot);
			
			is = null;
			os = null;
			
			is = new BufferedInputStream(new FileInputStream(RES_FILE));
			os = new BufferedOutputStream(new FileOutputStream(TAR_FILE));
			
			copy (is , os);
		}
		if (is != null) 
			is.close();
		if (os != null)
			os.close();
	}
	/**
	 * 文件拷贝的方法.在给定的文件夹里面找到包含传参作为后缀或者包含的文件名,并将其拷贝到目标文件夹
	 * 
	 * @param resDir resource root folder
	 * @param tarDir target root folder
	 * @param extention the list of name extended
	 * @param isInclude TRUE:this is the extension of file : FALSE the target file name includes extension
	 * @throws Exception 
	 * 
	 * @notice 
	 * File copy method :
	 * found inside pass parameter contains the file name as a suffix in the given folder , 
	 * then copied to the destination folder
	 * */
	public void copyFile(String resDir , String tarDir , List<String> extension , boolean isInclude) throws Exception{
		if (extension == null){
			throw new NullPointerException("input list can`t be null!");
		}
		for (int i = 0 ; i < extension.size() ; i ++) {
			copyFile(resDir , tarDir ,extension.get(i) , isInclude);
		}
	}
	
	/**
	 * 对俩文件进行拷贝操作
	 * 
	 * a copy of two file
	 * */
	public static void copy(File res , File tar) throws Exception {
		if (res == null || tar == null || !res.exists())
			throw new NullPointerException("parameter file must be exist in local!");
		
		if (!tar.exists())
			tar.createNewFile();
		
		InputStream is = 
				new BufferedInputStream(new FileInputStream(res));
		OutputStream os = 
				new BufferedOutputStream(new FileOutputStream(tar));
		
		byte[] bb = new byte[BUFFERED_SIZE];
		
		while (is.read(bb) > 0)
			os.write(bb);
		os.flush();
		is.close();
		os.close();
	}
	/**
	 * 单纯的文件拷贝
	 * 
	 * a single file copy
	 * */
	protected static void copy(InputStream is , OutputStream os) throws Exception {
		byte[] bb = new byte[BUFFERED_SIZE];
		while (is.read(bb) > 0)
			os.write(bb);
		os.flush();
	}
	
	/**
	 * 改变默认缓存大小
	 * 
	 * Change default buffer size
	 * */
	public void setSize(int size) {
		BUFFERED_SIZE = size;
	}
}
